package com.hjm.judge.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hjm.api.domain.JudgeSubmitDTO;
import com.hjm.api.domain.UserExeResult;
import com.hjm.api.domain.UserQuestionResultVO;
import com.hjm.common.core.constants.Constants;
import com.hjm.common.core.domain.Result;
import com.hjm.common.core.enums.CodeRunStatus;
import com.hjm.common.core.enums.UserIdentity;
import com.hjm.common.core.utils.JsonUtils;
import com.hjm.judge.constants.JudgeConstants;
import com.hjm.judge.domain.CaseJudgeResult;
import com.hjm.judge.domain.SandBoxExecuteResult;
import com.hjm.judge.domain.UserSubmit;
import com.hjm.judge.mapper.UserSubmitMapper;
import com.hjm.judge.service.IJudgeService;
import com.hjm.judge.service.ISandBoxPoolService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class JudgeServiceImpl extends ServiceImpl<UserSubmitMapper, UserSubmit> implements IJudgeService {

    @Autowired
    private ISandBoxPoolService sandBoxPoolService;

    @Autowired
    private UserSubmitMapper userSubmitMapper;

    @Override
    public Result<UserQuestionResultVO> doJudgeJavaCode(JudgeSubmitDTO judgeSubmitDTO) {
        // 在沙箱中 进行代码的 编译与 执行
        SandBoxExecuteResult executeResult = sandBoxPoolService.executeJavaCode(judgeSubmitDTO.getUserId(),
                judgeSubmitDTO.getInputList(), judgeSubmitDTO.getUserCode());

        UserQuestionResultVO userQuestionResultVO = new UserQuestionResultVO();
        UserSubmit userSubmit = new UserSubmit();
        // 根据 沙箱执行结果进行 判断
        if (executeResult != null && CodeRunStatus.SUCCEED.equals(executeResult.getRunStatus())) {
            userSubmit = doJudge(judgeSubmitDTO, judgeSubmitDTO.getInputList(), judgeSubmitDTO.getOutputList(), executeResult.getOutputList(),
                    judgeSubmitDTO.getSpaceLimit(), executeResult.getUseMemory(),
                    judgeSubmitDTO.getTimeLimit(), executeResult.getUseTime());
        } else {
            // 沙箱执行失败
            userSubmit = new UserSubmit();
            BeanUtils.copyProperties(judgeSubmitDTO, userSubmit);
            userSubmit.setPass(Constants.FALSE);
            userSubmit.setScore(JudgeConstants.ERROR_SCORE);
            if (executeResult != null) {
                // todo 这里需要 修改 caseJudgeRes
//                List<CaseJudgeResult> caseJudgeResultList = new ArrayList<>();
//                for (int i = 0; i < judgeSubmitDTO.getInputList().size(); i++) {
//                    CaseJudgeResult caseJudgeResult = new CaseJudgeResult();
//                    caseJudgeResult.setInput(judgeSubmitDTO.getInputList().get(i));
//                    String expectOutput = executeResult.getOutputList().get(i);
//                    caseJudgeResult.setExpectedOutput(expectOutput);
//
//                    caseJudgeResultList.add(caseJudgeResult);
//                }
                userSubmit.setCaseJudgeRes(JSON.toJSONString(new ArrayList<>()));

                userSubmit.setErrorMessage(executeResult.getErrorMsg());  //将错误信息返回
            }else{
                userSubmit.setErrorMessage(CodeRunStatus.UNKNOWN_FAILED.getMsg());
            }
        }

        // 不管是否通过 都需要保存到数据库
        saveUserSubmit(userSubmit);

        // 将结果转换为 UserQuestionResultVO 对象
        userQuestionResultVO.setPass(userSubmit.getPass());
        userQuestionResultVO.setResults(JsonUtils.toList(userSubmit.getCaseJudgeRes(), UserExeResult.class));
        userQuestionResultVO.setErrorMsg(userSubmit.getErrorMessage());

        return Result.ok(userQuestionResultVO);

    }


    // 保存到数据库
    private void saveUserSubmit(UserSubmit userSubmit) {
        UserSubmit lastSubmit = userSubmitMapper.selectOne(new LambdaQueryWrapper<UserSubmit>()
                .eq(UserSubmit::getUserId, userSubmit.getUserId())
                .eq(UserSubmit::getQuestionId, userSubmit.getQuestionId())
                .isNull(userSubmit.getExamId() == null, UserSubmit::getExamId)
                .eq(userSubmit.getExamId() != null, UserSubmit::getExamId, userSubmit.getExamId()));

        if (lastSubmit != null) {
            userSubmit.setSubmitId(lastSubmit.getSubmitId());
        }
        // 1 表示 管理员 添加的
        userSubmit.setCreateBy(Long.valueOf(UserIdentity.ADMIN.getValue()));
        saveOrUpdate(userSubmit);
    }


    // 判题
    private  UserSubmit doJudge(JudgeSubmitDTO submitDTO, List<String> inputList, List<String> expectOutputList,
                                      List<String> executeOutputList,
                                      Long spaceLimit, Long useMemory, Long timeLimit, Long useTime) {
        UserSubmit userSubmit = new UserSubmit();
        BeanUtils.copyProperties(submitDTO, userSubmit);
        userSubmit.setPass(Constants.FALSE); //用户代码是否执行通过  默认设置为未通过
        // 判断 exp预期输出结果和 exe输出结果   数量 是否一致
        if (expectOutputList.size() != executeOutputList.size()) {
            userSubmit.setScore(JudgeConstants.ERROR_SCORE);
            userSubmit.setErrorMessage(JudgeConstants.ERROR_ANSWER);
            return userSubmit;
        }

        boolean allPassed = true;
        int caseSize = inputList.size();
        int outPutSize = executeOutputList.size();
        List<CaseJudgeResult> caseJudgeResultList = new ArrayList<>();

        // 这里根据 输入 来比较 实际输出结果 和 预期输出结果
        for (int i = 0; i < caseSize; i++) {
            CaseJudgeResult caseJudgeResult = new CaseJudgeResult();
            caseJudgeResult.setInput(inputList.get(i));
            String expectOutput = expectOutputList.get(i);
            caseJudgeResult.setExpectedOutput(expectOutput);
           if (i < outPutSize) {
               String output = executeOutputList.get(i);
               caseJudgeResult.setOutput(output);
               if (!expectOutput.equals(output)) {
                   allPassed = false;
               }
           } else {
               allPassed = false;
           }
            caseJudgeResultList.add(caseJudgeResult);
        }
        userSubmit.setCaseJudgeRes(JSON.toJSONString(caseJudgeResultList));

        // 如果有一个不对 则判题失败
        if (!allPassed) {
            userSubmit.setScore(JudgeConstants.ERROR_SCORE);
            userSubmit.setErrorMessage(JudgeConstants.ERROR_ANSWER);
            return userSubmit;
        }
        // 判断空间限制和时间限制
        if (spaceLimit != null && useMemory > spaceLimit) {
            userSubmit.setScore(JudgeConstants.ERROR_SCORE);
            userSubmit.setErrorMessage(JudgeConstants.OUT_OF_MEMORY);
            return userSubmit;
        }
        if (timeLimit != null && useTime > timeLimit) {
            userSubmit.setScore(JudgeConstants.ERROR_SCORE);
            userSubmit.setErrorMessage(JudgeConstants.OUT_OF_TIME);
            return userSubmit;
        }
        // 判题通过 计算得分
        //  得分 = 基础分 * 难度系数
        int score = JudgeConstants.DEFAULT_SCORE * submitDTO.getDifficulty();
        userSubmit.setScore(score);
        userSubmit.setPass(Constants.TRUE);
        return userSubmit;
    }
}
